home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / contrib / pdcurs22 / src / private / pdcutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-26  |  16.1 KB  |  565 lines

  1. /*
  2. ***************************************************************************
  3. * This file comprises part of PDCurses. PDCurses is Public Domain software.
  4. * You may use this code for whatever purposes you desire. This software
  5. * is provided AS IS with NO WARRANTY whatsoever.
  6. * Should this software be used in another application, an acknowledgement
  7. * that PDCurses code is used would be appreciated, but is not mandatory.
  8. *
  9. * Any changes which you make to this software which may improve or enhance
  10. * it, should be forwarded to the current maintainer for the benefit of 
  11. * other users.
  12. *
  13. * The only restriction placed on this code is that no distribution of
  14. * modified PDCurses code be made under the PDCurses name, by anyone
  15. * other than the current maintainer.
  16. * See the file maintain.er for details of the current maintainer.
  17. ***************************************************************************
  18. */
  19. #define    CURSES_LIBRARY    1
  20. #include <curses.h>
  21. #undef PDC_usleep
  22.  
  23. #if defined(DOS) && defined(MSC) || defined(XCURSES)
  24. #include <time.h>
  25. #endif
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <stdio.h>
  31. #include <stdarg.h>
  32. #include <limits.h>
  33. #include <signal.h>
  34.  
  35. #ifdef PDCDEBUG
  36. char *rcsid_PDCutil  = "$Id$";
  37. #endif
  38.  
  39. /*man-start*********************************************************************
  40.  
  41.   PDC_memmove()    - Replacement memmove() for lacking compliers.
  42.  
  43.   PDCurses Description:
  44.      This is a private PDCurses routine.
  45.  
  46.      Move a portion of memory taking consideration of overlapping memory
  47.      areas.
  48.  
  49.   PDCurses Return Value:
  50.      This function returns NULL if no temporary memory could be allocated.
  51.  
  52.   Portability:
  53.      PDCurses    int PDC_memmove(void *s1,const void *s2,size_t n);
  54.  
  55. **man-end**********************************************************************/
  56.  
  57.  
  58. void *PDC_memmove (void *s1, const void *s2, size_t n)
  59. {
  60.   char *dd=NULL;
  61.   const char *ss=NULL;
  62.  
  63.   dd = (char *)s1;
  64.   ss = (const char *)s2;
  65.   if (dd > ss && dd < ss + n)
  66.     {
  67.       dd += n;
  68.       ss += n;
  69.       while (n--)
  70.         *--dd = *--ss;
  71.     }
  72.   else
  73.     while (n--)
  74.       *dd++ = *ss++;
  75.   return s1;
  76. }
  77.  
  78. /*man-start*********************************************************************
  79.  
  80.   PDC_usleep()    - waits for specified number of microseconds
  81.  
  82.   PDCurses Description:
  83.      This routine is intended to provide a mechanism to wait the
  84.      specified number of microseconds. This routine is provided for
  85.      users of the Microsoft compilers under DOS as the default
  86.      library does not provide a suitable function.
  87.      Under any other Operating System/Compiler option, this function
  88.      does nothing.
  89.  
  90.   Portability:
  91.      PDCurses    void PDC_usleep( clock_t );
  92.  
  93.   Acknowledgement
  94.      PDC_usleep() was written by John Steele  (jsteele@netcom.com)
  95.  
  96. **man-end**********************************************************************/
  97.  
  98. #if defined(DOS) && defined(MSC)
  99. void    PDC_usleep(clock_t wait)
  100. {
  101.     clock_t goal;
  102. #ifdef PDCDEBUG
  103.     if (trace_on) PDC_debug("PDC_usleep() - called\n");
  104. #endif
  105.  
  106.     goal = wait + clock();
  107.     while (goal > clock())
  108.     ;
  109.     return;
  110. }
  111. #endif
  112.  
  113. #if defined(XCURSES) && defined(HAS_POLL)
  114. # include <poll.h>
  115. void    PDC_usleep(long wait)
  116. {
  117.     struct pollfd fd;
  118. #ifdef PDCDEBUG
  119.     if (trace_on) PDC_debug("PDC_usleep() - called\n");
  120. #endif
  121.     poll(&fd,0L,wait);
  122.     return;
  123. }
  124. #endif
  125.  
  126. #if defined(XCURSES) && defined(HAS_USLEEP)
  127. void    PDC_usleep(long wait)
  128. {
  129. #ifdef PDCDEBUG
  130.     if (trace_on) PDC_debug("PDC_usleep() - called\n");
  131. #endif
  132.     usleep(wait);
  133.     return;
  134. }
  135. #endif
  136.  
  137. /*
  138.  * This module is based on vsscanf.c and input.c from emx 0.8f library
  139.  * source which is Copyright (c) 1990-1992 by Eberhard Mattes.
  140.  * Eberhard Mattes has kindly agreed to allow this module to be incorporated
  141.  * into PDCurses.
  142.  */
  143.  
  144. /*man-start*********************************************************************
  145.  
  146.   PDC_vsscanf()    - Internal routine to parse and format an input buffer.
  147.  
  148.   PDCurses Description:
  149.      This is a private PDCurses routine.
  150.  
  151.      Scan a series of input fields. Each field is formatted according to
  152.      a supplied format string and the formatted input is stored in the
  153.      variable number of addresses passed.
  154.  
  155.   PDCurses Return Value:
  156.      This function returns the number of input fields or EOF on error.
  157.  
  158.   PDCurses Errors:
  159.      If the supplied data is invalid or an incorrect number of arguments
  160.      are passed, EOF is returned as an error.
  161.  
  162.   Portability:
  163.      PDCurses    int PDC_vsscanf(char *buf,const char *fmt,va_list arg_ptr);
  164.  
  165. **man-end**********************************************************************/
  166.  
  167. #define WHITE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
  168.  
  169. #define NEXT(x) \
  170.         do { \
  171.             x = *buf++; \
  172.             if (x == '\0') \
  173.                return (count == 0 ? EOF : count); \
  174.             ++chars; \
  175.            } while (0)
  176.  
  177. #define UNGETC(x) \
  178.         do { \
  179.             --buf; *buf = x; --chars; \
  180.            } while (0)
  181.  
  182. int PDC_vsscanf ( char *buf, const char *fmt, char *arg_ptr)
  183. {
  184.     int count, chars, c, width, radix, d, i;
  185.     int *int_ptr;
  186.     long *long_ptr;
  187.     short *short_ptr;
  188.     char *char_ptr;
  189.     unsigned char f;
  190.     char neg, assign, ok, size;
  191.     unsigned long n;
  192.     char map[256], end;
  193.     double dx, dd, *dbl_ptr;
  194.     float *flt_ptr;
  195.     int exp;
  196.     char eneg;
  197.  
  198. #ifdef PDCDEBUG
  199. #define bool unsigned char
  200.     extern bool trace_on; /* this is explicit here as curses.h is not #included */
  201.     if (trace_on) PDC_debug("PDC_vsscanf() - called\n");
  202. #endif
  203.  
  204.   count = 0; chars = 0; c = 0;
  205.   while ((f = *fmt) != 0)
  206.     {
  207.       if (WHITE (f))
  208.         {
  209.           do
  210.             {
  211.               ++fmt; f = *fmt;
  212.             } while (WHITE (f));
  213.           do
  214.             {
  215.               c = *buf++;
  216.               if (c == '\0')
  217.                 {
  218.                   if (f == 0 || count != 0)
  219.                     return (count);
  220.                   else
  221.                     return (EOF);
  222.                 }
  223.               else
  224.                 ++chars;
  225.             } while (WHITE (c));
  226.           UNGETC (c);
  227.         }
  228.       else if (f != '%')
  229.         {
  230.           NEXT (c);
  231.           if (c != f)
  232.             return (count);
  233.           ++fmt;
  234.         }
  235.       else
  236.         {
  237.           assign = TRUE; width = INT_MAX;
  238.           char_ptr = NULL;
  239.           ++fmt;
  240.           if (*fmt == '*')
  241.             {
  242.               assign = FALSE;
  243.               ++fmt;
  244.             }
  245.           if (isdigit (*fmt))
  246.             {
  247.               width = 0;
  248.               while (isdigit (*fmt))
  249.                 width = width * 10 + (*fmt++ - '0');
  250.               if (width == 0) width = INT_MAX;
  251.             }
  252.           size = 0;
  253.           if (*fmt == 'h' || *fmt == 'l')
  254.             size = *fmt++;
  255.           f = *fmt;
  256.           switch (f)
  257.             {
  258.             case 'c':
  259.               if (width == INT_MAX)
  260.                 width = 1;
  261.               if (assign)
  262.                 char_ptr = va_arg (arg_ptr, char *);
  263.               while (width > 0)
  264.                 {
  265.                   --width;
  266.                   NEXT (c);
  267.                   if (assign)
  268.                     {
  269.                       *char_ptr++ = (char)c;
  270.                       ++count;
  271.                     }
  272.                 }
  273.               break;
  274.             case '[':
  275.               (void)memset (map, 0, 256);
  276.               end = 0;
  277.               ++fmt;
  278.               if (*fmt == '^')
  279.                 {
  280.                   ++fmt; end = 1;
  281.                 }
  282.               i = 0;
  283.               for (;;)
  284.                 {
  285.                   f = (unsigned char)*fmt;
  286.                   switch (f)
  287.                     {
  288.                     case 0:
  289.                       --fmt;       /* avoid skipping past 0 */
  290.                       NEXT (c);
  291.                       goto string;
  292.                     case ']':
  293.                       if (i > 0)
  294.                         {
  295.                           NEXT (c);
  296.                           goto string;
  297.                         }
  298.                       /* no break */
  299.                     default:
  300.                       if (fmt[1] == '-' && fmt[2] != 0 &&
  301.                           f < (unsigned char)fmt[2])
  302.                         {
  303.                           (void)memset (map+f, 1, (unsigned char)fmt[2]-f);
  304.                           fmt += 2;
  305.                         }
  306.                       else
  307.                         map[f] = 1;
  308.                       break;
  309.                     }
  310.                   ++fmt; ++i;
  311.                 }
  312.             case 's':
  313.               (void)memset (map, 0, 256);
  314.               map[' '] = 1;
  315.               map['\n'] = 1;
  316.               map['\r'] = 1;
  317.               map['\t'] = 1;
  318.               end = 1;
  319.               do
  320.                 {
  321.                   NEXT (c);
  322.                 } while (WHITE (c));
  323. string:
  324.               if (assign)
  325.                 char_ptr = va_arg (arg_ptr, char *);
  326.               while (width > 0 && map[(unsigned char)c] != end)
  327.                 {
  328.                   --width;
  329.                   if (assign)
  330.                     *char_ptr++ = (char)c;
  331.                   c = *buf++;
  332.                   if (c == '\0')
  333.                     break;
  334.                   else
  335.                     ++chars;
  336.                 }
  337.               if (assign)
  338.                 {
  339.                   *char_ptr = 0;
  340.                   ++count;
  341.                 }
  342.               if (c == '\0')
  343.                 return (count);
  344.               else
  345.                 UNGETC (c);
  346.               break;
  347.             case 'f':
  348.             case 'e':
  349.             case 'E':
  350.             case 'g':
  351.             case 'G':
  352.               neg = ok = FALSE; dx = 0.0;
  353.               do
  354.                 {
  355.                   NEXT (c);
  356.                 } while (WHITE (c));
  357.               if (c == '+')
  358.                 {
  359.                   NEXT (c); --width;
  360.                 }
  361.               else if (c == '-')
  362.                 {
  363.                   neg = TRUE; NEXT (c); --width;
  364.                 }
  365.               while (width > 0 && isdigit (c))
  366.                 {
  367.                   --width;
  368.                   dx = dx * 10.0 + (double)(c - '0');
  369.                   ok = TRUE;
  370.                   c = *buf++;
  371.                   if (c == '\0')
  372.                     break;
  373.                   else
  374.                     ++chars;
  375.                 }
  376.               if (width > 0 && c == '.')
  377.                 {
  378.                   --width;
  379.                   dd = 10.0; NEXT (c);
  380.                   while (width > 0 && isdigit (c))
  381.                     {
  382.                       --width;
  383.                       dx += (double)(c - '0') / dd;
  384.                       dd *= 10.0;
  385.                       ok = TRUE;
  386.                       c = *buf++;
  387.                       if (c == '\0')
  388.                         break;
  389.                       else
  390.                         ++chars;
  391.                     }
  392.                 }
  393.               if (!ok)
  394.                 return (count);
  395.               if (width > 0 && (c == 'e' || c == 'E'))
  396.                 {
  397.                   eneg = FALSE; exp = 0; NEXT (c); --width;
  398.                   if (width > 0 && c == '+')
  399.                     {
  400.                       NEXT (c); --width;
  401.                     }
  402.                   else if (width > 0 && c == '-')
  403.                     {
  404.                       eneg = TRUE; NEXT (c); --width;
  405.                     }
  406.                   if (!(width > 0 && isdigit (c)))
  407.                     {
  408.                       UNGETC (c);
  409.                       return (count);
  410.                     }
  411.                   while (width > 0 && isdigit (c))
  412.                     {
  413.                       --width;
  414.                       exp = exp * 10 + (c - '0');
  415.                       c = *buf++;
  416.                       if (c == '\0')
  417.                         break;
  418.                       else
  419.                         ++chars;
  420.                     }
  421.                   if (eneg) exp = -exp;
  422.                   while (exp > 0)
  423.                     {
  424.                       dx *= 10.0;
  425.                       --exp;
  426.                     }
  427.                   while (exp < 0)
  428.                     {
  429.                       dx /= 10.0;
  430.                       ++exp;
  431.                     }
  432.                 }
  433.               if (assign)
  434.                 {
  435.                   if (neg) dx = -dx;
  436.                   if (size == 'l')
  437.                     {
  438.                       dbl_ptr = va_arg (arg_ptr, double *);
  439.                       *dbl_ptr = dx;
  440.                     }
  441.                   else
  442.                     {
  443.                       flt_ptr = va_arg (arg_ptr, float *);
  444.                       *flt_ptr = (float)dx;
  445.                     }
  446.                   ++count;
  447.                 }
  448.               if (c == '\0')
  449.                 return (count);
  450.               else
  451.                 UNGETC (c);
  452.               break;
  453.             case 'i':
  454.               neg = FALSE; radix = 10;
  455.               do
  456.                 {
  457.                   NEXT (c);
  458.                 } while (WHITE (c));
  459.               if (!(width > 0 && c == '0'))
  460.                 goto scan_complete_number;
  461.               NEXT (c); --width;
  462.               if (width > 0 && (c == 'x' || c == 'X'))
  463.                 {
  464.                   NEXT (c); radix = 16; --width;
  465.                 }
  466.               else if (width > 0 && (c >= '0' && c <= '7'))
  467.                 radix = 8;
  468.               goto scan_unsigned_number;
  469.             case 'd':
  470.             case 'u':
  471.             case 'o':
  472.             case 'x':
  473.             case 'X':
  474.               do
  475.                 {
  476.                   NEXT (c);
  477.                 } while (WHITE (c));
  478.               switch (f)
  479.                 {
  480.                 case 'o':           radix = 8; break;
  481.                 case 'x': case 'X': radix = 16; break;
  482.                 default:            radix = 10; break;
  483.                 }
  484. scan_complete_number:
  485.               neg = FALSE;
  486.               if (width > 0 && c == '+')
  487.                 {
  488.                   NEXT (c); --width;
  489.                 }
  490.               else if (width > 0 && c == '-' && radix == 10)
  491.                 {
  492.                   neg = TRUE; NEXT (c); --width;
  493.                 }
  494. scan_unsigned_number:
  495.               n = 0; ok = FALSE;
  496.               while (width > 0)
  497.                 {
  498.                   --width;
  499.                   if (isdigit (c))
  500.                     d = c - '0';
  501.                   else if (isupper (c))
  502.                     d = c - 'A' + 10;
  503.                   else if (islower (c))
  504.                     d = c - 'a' + 10;
  505.                   else
  506.                     break;
  507.                   if (d < 0 || d >= radix)
  508.                     break;
  509.                   ok = TRUE;
  510.                   n = n * radix + d;
  511.                   c = *buf++;
  512.                   if (c == '\0')
  513.                     break;
  514.                   else
  515.                     ++chars;
  516.                 }
  517.               if (!ok)
  518.                 return (count);
  519.               if (assign)
  520.                 {
  521.                   if (neg) n = -n;
  522.                   switch(size)
  523.                      {
  524.                       case 'h':
  525.                               short_ptr = va_arg (arg_ptr, short *);
  526.                               *short_ptr = (short)n;
  527.                               break;
  528.                       case 'l':
  529.                               long_ptr = va_arg (arg_ptr, long *);
  530.                               *long_ptr = (long)n;
  531.                               break;
  532.                       default:
  533.                               int_ptr = va_arg (arg_ptr, int *);
  534.                               *int_ptr = (int)n;
  535.                      }
  536.                   ++count;
  537.                 }
  538.               if (c == '\0')
  539.                 return (count);
  540.               else
  541.                 UNGETC (c);
  542.               break;
  543.             case 'n':
  544.               if (assign)
  545.                 {
  546.                   int_ptr = va_arg (arg_ptr, int *);
  547.                   *int_ptr = chars;
  548.                   ++count;
  549.                 }
  550.               break;
  551.             default:
  552.               if (f == 0)                 /* % at end of string */
  553.                 return (count);
  554.               NEXT (c);
  555.               if (c != f)
  556.                 return (count);
  557.               break;
  558.             }
  559.           ++fmt;
  560.         }
  561.     }
  562.   return (count);
  563. }
  564.